home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / language / harvest.cpt / Harvest C / Tcl 6.2 / tclUtil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-13  |  37.0 KB  |  1,507 lines

  1. /* 
  2.  * tclUtil.c --
  3.  *
  4.  *    This file contains utility procedures that are used by many Tcl
  5.  *    commands.
  6.  *
  7.  * Copyright 1987-1991 Regents of the University of California
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /user6/ouster/tcl/RCS/tclUtil.c,v 1.62 91/12/02 11:56:29 ouster Exp $ SPRITE (Berkeley)";
  19. #endif
  20.  
  21. #include "tclInt.h"
  22.  
  23. /*
  24.  * The following values are used in the flags returned by Tcl_ScanElement
  25.  * and used by Tcl_ConvertElement.  The value TCL_DONT_USE_BRACES is also
  26.  * defined in tcl.h;  make sure its value doesn't overlap with any of the
  27.  * values below.
  28.  *
  29.  * TCL_DONT_USE_BRACES -    1 means the string mustn't be enclosed in
  30.  *                braces (e.g. it contains unmatched braces,
  31.  *                or ends in a backslash character, or user
  32.  *                just doesn't want braces);  handle all
  33.  *                special characters by adding backslashes.
  34.  * USE_BRACES -            1 means the string contains a special
  35.  *                character that can be handled simply by
  36.  *                enclosing the entire argument in braces.
  37.  * BRACES_UNMATCHED -        1 means that braces aren't properly matched
  38.  *                in the argument.
  39.  */
  40.  
  41. #define USE_BRACES        2
  42. #define BRACES_UNMATCHED    4
  43.  
  44. /*
  45.  * The variable below is set to NULL before invoking regexp functions
  46.  * and checked after those functions.  If an error occurred then regerror
  47.  * will set the variable to point to a (static) error message.  This
  48.  * mechanism unfortunately does not support multi-threading, but then
  49.  * neither does the rest of the regexp facilities.
  50.  */
  51.  
  52. char *tclRegexpError = NULL;
  53.  
  54. #ifdef macintosh
  55. #    pragma segment tclUtil
  56. #ifndef isascii
  57. #define isascii(c) (1)
  58. #endif
  59. #endif
  60.  
  61. /*
  62.  * Function prototypes for local procedures in this file:
  63.  */
  64.  
  65. static void        SetupAppendBuffer _ANSI_ARGS_((Interp *iPtr,
  66.                 int newSpace));
  67.  
  68. /*
  69.  *----------------------------------------------------------------------
  70.  *
  71.  * TclFindElement --
  72.  *
  73.  *    Given a pointer into a Tcl list, locate the first (or next)
  74.  *    element in the list.
  75.  *
  76.  * Results:
  77.  *    The return value is normally TCL_OK, which means that the
  78.  *    element was successfully located.  If TCL_ERROR is returned
  79.  *    it means that list didn't have proper list structure;
  80.  *    interp->result contains a more detailed error message.
  81.  *
  82.  *    If TCL_OK is returned, then *elementPtr will be set to point
  83.  *    to the first element of list, and *nextPtr will be set to point
  84.  *    to the character just after any white space following the last
  85.  *    character that's part of the element.  If this is the last argument
  86.  *    in the list, then *nextPtr will point to the NULL character at the
  87.  *    end of list.  If sizePtr is non-NULL, *sizePtr is filled in with
  88.  *    the number of characters in the element.  If the element is in
  89.  *    braces, then *elementPtr will point to the character after the
  90.  *    opening brace and *sizePtr will not include either of the braces.
  91.  *    If there isn't an element in the list, *sizePtr will be zero, and
  92.  *    both *elementPtr and *termPtr will refer to the null character at
  93.  *    the end of list.  Note:  this procedure does NOT collapse backslash
  94.  *    sequences.
  95.  *
  96.  * Side effects:
  97.  *    None.
  98.  *
  99.  *----------------------------------------------------------------------
  100.  */
  101.  
  102. int
  103. TclFindElement(interp, list, elementPtr, nextPtr, sizePtr, bracePtr)
  104.     Tcl_Interp *interp;        /* Interpreter to use for error reporting. */
  105.     register char *list;    /* String containing Tcl list with zero
  106.                  * or more elements (possibly in braces). */
  107.     char **elementPtr;        /* Fill in with location of first significant
  108.                  * character in first element of list. */
  109.     char **nextPtr;        /* Fill in with location of character just
  110.                  * after all white space following end of
  111.                  * argument (i.e. next argument or end of
  112.                  * list). */
  113.     int *sizePtr;        /* If non-zero, fill in with size of
  114.                  * element. */
  115.     int *bracePtr;        /* If non-zero fill in with non-zero/zero
  116.                  * to indicate that arg was/wasn't
  117.                  * in braces. */
  118. {
  119.     register char *p;
  120.     int openBraces = 0;
  121.     int inQuotes = 0;
  122.     int size;
  123.  
  124.     /*
  125.      * Skim off leading white space and check for an opening brace or
  126.      * quote.   Note:  use of "isascii" below and elsewhere in this
  127.      * procedure is a temporary hack (7/27/90) because Mx uses characters
  128.      * with the high-order bit set for some things.  This should probably
  129.      * be changed back eventually, or all of Tcl should call isascii.
  130.      */
  131.  
  132.     while (isascii(*list) && isspace(*list)) {
  133.     list++;
  134.     }
  135.     if (*list == '{') {
  136.     openBraces = 1;
  137.     list++;
  138.     } else if (*list == '"') {
  139.     inQuotes = 1;
  140.     list++;
  141.     }
  142.     if (bracePtr != 0) {
  143.     *bracePtr = openBraces;
  144.     }
  145.     p = list;
  146.  
  147.     /*
  148.      * Find the end of the element (either a space or a close brace or
  149.      * the end of the string).
  150.      */
  151.  
  152.     while (1) {
  153.     switch (*p) {
  154.  
  155.         /*
  156.          * Open brace: don't treat specially unless the element is
  157.          * in braces.  In this case, keep a nesting count.
  158.          */
  159.  
  160.         case '{':
  161.         if (openBraces != 0) {
  162.             openBraces++;
  163.         }
  164.         break;
  165.  
  166.         /*
  167.          * Close brace: if element is in braces, keep nesting
  168.          * count and quit when the last close brace is seen.
  169.          */
  170.  
  171.         case '}':
  172.         if (openBraces == 1) {
  173.             char *p2;
  174.  
  175.             size = p - list;
  176.             p++;
  177.             if ((isascii(*p) && isspace(*p)) || (*p == 0)) {
  178.             goto done;
  179.             }
  180.             for (p2 = p; (*p2 != 0) && (!isspace(*p2)) && (p2 < p+20);
  181.                 p2++) {
  182.             /* null body */
  183.             }
  184.             Tcl_ResetResult(interp);
  185.             sprintf(interp->result,
  186.                 "list element in braces followed by \"%.*s\" instead of space",
  187.                 p2-p, p);
  188.             return TCL_ERROR;
  189.         } else if (openBraces != 0) {
  190.             openBraces--;
  191.         }
  192.         break;
  193.  
  194.         /*
  195.          * Backslash:  skip over everything up to the end of the
  196.          * backslash sequence.
  197.          */
  198.  
  199.         case '\\': {
  200.         int size;
  201.  
  202.         (void) Tcl_Backslash(p, &size);
  203.         p += size - 1;
  204.         break;
  205.         }
  206.  
  207.         /*
  208.          * Space: ignore if element is in braces or quotes;  otherwise
  209.          * terminate element.
  210.          */
  211.  
  212.         case ' ':
  213.         case '\f':
  214.         case '\n':
  215.         case '\r':
  216.         case '\t':
  217.         case '\v':
  218.         if ((openBraces == 0) && !inQuotes) {
  219.             size = p - list;
  220.             goto done;
  221.         }
  222.         break;
  223.  
  224.         /*
  225.          * Double-quote:  if element is in quotes then terminate it.
  226.          */
  227.  
  228.         case '"':
  229.         if (inQuotes) {
  230.             char *p2;
  231.  
  232.             size = p-list;
  233.             p++;
  234.             if ((isascii(*p) && isspace(*p)) || (*p == 0)) {
  235.             goto done;
  236.             }
  237.             for (p2 = p; (*p2 != 0) && (!isspace(*p2)) && (p2 < p+20);
  238.                 p2++) {
  239.             /* null body */
  240.             }
  241.             Tcl_ResetResult(interp);
  242.             sprintf(interp->result,
  243.                 "list element in quotes followed by \"%.*s\" %s",
  244.                 p2-p, p, "instead of space");
  245.             return TCL_ERROR;
  246.         }
  247.         break;
  248.  
  249.         /*
  250.          * End of list:  terminate element.
  251.          */
  252.  
  253.         case 0:
  254.         if (openBraces != 0) {
  255.             Tcl_SetResult(interp, "unmatched open brace in list",
  256.                 TCL_STATIC);
  257.             return TCL_ERROR;
  258.         } else if (inQuotes) {
  259.             Tcl_SetResult(interp, "unmatched open quote in list",
  260.                 TCL_STATIC);
  261.             return TCL_ERROR;
  262.         }
  263.         size = p - list;
  264.         goto done;
  265.  
  266.     }
  267.     p++;
  268.     }
  269.  
  270.     done:
  271.     while (isascii(*p) && isspace(*p)) {
  272.     p++;
  273.     }
  274.     *elementPtr = list;
  275.     *nextPtr = p;
  276.     if (sizePtr != 0) {
  277.     *sizePtr = size;
  278.     }
  279.     return TCL_OK;
  280. }
  281.  
  282. /*
  283.  *----------------------------------------------------------------------
  284.  *
  285.  * TclCopyAndCollapse --
  286.  *
  287.  *    Copy a string and eliminate any backslashes that aren't in braces.
  288.  *
  289.  * Results:
  290.  *    There is no return value.  Count chars. get copied from src
  291.  *    to dst.  Along the way, if backslash sequences are found outside
  292.  *    braces, the backslashes are eliminated in the copy.
  293.  *    After scanning count chars. from source, a null character is
  294.  *    placed at the end of dst.
  295.  *
  296.  * Side effects:
  297.  *    None.
  298.  *
  299.  *----------------------------------------------------------------------
  300.  */
  301.  
  302. void
  303. TclCopyAndCollapse(count, src, dst)
  304.     int count;            /* Total number of characters to copy
  305.                  * from src. */
  306.     register char *src;        /* Copy from here... */
  307.     register char *dst;        /* ... to here. */
  308. {
  309.     register char c;
  310.     int numRead;
  311.  
  312.     for (c = *src; count > 0; src++, c = *src, count--) {
  313.     if (c == '\\') {
  314.         *dst = Tcl_Backslash(src, &numRead);
  315.         if (*dst != 0) {
  316.         dst++;
  317.         }
  318.         src += numRead-1;
  319.         count -= numRead-1;
  320.     } else {
  321.         *dst = c;
  322.         dst++;
  323.     }
  324.     }
  325.     *dst = 0;
  326. }
  327.  
  328. /*
  329.  *----------------------------------------------------------------------
  330.  *
  331.  * Tcl_SplitList --
  332.  *
  333.  *    Splits a list up into its constituent fields.
  334.  *
  335.  * Results
  336.  *    The return value is normally TCL_OK, which means that
  337.  *    the list was successfully split up.  If TCL_ERROR is
  338.  *    returned, it means that "list" didn't have proper list
  339.  *    structure;  interp->result will contain a more detailed
  340.  *    error message.
  341.  *
  342.  *    *argvPtr will be filled in with the address of an array
  343.  *    whose elements point to the elements of list, in order.
  344.  *    *argcPtr will get filled in with the number of valid elements
  345.  *    in the array.  A single block of memory is dynamically allocated
  346.  *    to hold both the argv array and a copy of the list (with
  347.  *    backslashes and braces removed in the standard way).
  348.  *    The caller must eventually free this memory by calling free()
  349.  *    on *argvPtr.  Note:  *argvPtr and *argcPtr are only modified
  350.  *    if the procedure returns normally.
  351.  *
  352.  * Side effects:
  353.  *    Memory is allocated.
  354.  *
  355.  *----------------------------------------------------------------------
  356.  */
  357.  
  358. int
  359. Tcl_SplitList(interp, list, argcPtr, argvPtr)
  360.     Tcl_Interp *interp;        /* Interpreter to use for error reporting. */
  361.     char *list;            /* Pointer to string with list structure. */
  362.     int *argcPtr;        /* Pointer to location to fill in with
  363.                  * the number of elements in the list. */
  364.     char ***argvPtr;        /* Pointer to place to store pointer to array
  365.                  * of pointers to list elements. */
  366. {
  367.     char **argv;
  368.     register char *p;
  369.     int size, i, result, elSize, brace;
  370.     char *element;
  371.  
  372.     /*
  373.      * Figure out how much space to allocate.  There must be enough
  374.      * space for both the array of pointers and also for a copy of
  375.      * the list.  To estimate the number of pointers needed, count
  376.      * the number of space characters in the list.
  377.      */
  378.  
  379.     for (size = 1, p = list; *p != 0; p++) {
  380.     if (isspace(*p)) {
  381.         size++;
  382.     }
  383.     }
  384.     size++;            /* Leave space for final NULL pointer. */
  385.     argv = (char **) ckalloc((unsigned)
  386.         ((size * sizeof(char *)) + (p - list) + 1));
  387.     for (i = 0, p = ((char *) argv) + size*sizeof(char *);
  388.         *list != 0; i++) {
  389.     result = TclFindElement(interp, list, &element, &list, &elSize, &brace);
  390.     if (result != TCL_OK) {
  391.         ckfree((char *) argv);
  392.         return result;
  393.     }
  394.     if (*element == 0) {
  395.         break;
  396.     }
  397.     if (i >= size) {
  398.         ckfree((char *) argv);
  399.         Tcl_SetResult(interp, "internal error in Tcl_SplitList",
  400.             TCL_STATIC);
  401.         return TCL_ERROR;
  402.     }
  403.     argv[i] = p;
  404.     if (brace) {
  405.         strncpy(p, element, elSize);
  406.         p += elSize;
  407.         *p = 0;
  408.         p++;
  409.     } else {
  410.         TclCopyAndCollapse(elSize, element, p);
  411.         p += elSize+1;
  412.     }
  413.     }
  414.  
  415.     argv[i] = NULL;
  416.     *argvPtr = argv;
  417.     *argcPtr = i;
  418.     return TCL_OK;
  419. }
  420.  
  421. /*
  422.  *----------------------------------------------------------------------
  423.  *
  424.  * Tcl_ScanElement --
  425.  *
  426.  *    This procedure is a companion procedure to Tcl_ConvertElement.
  427.  *    It scans a string to see what needs to be done to it (e.g.
  428.  *    add backslashes or enclosing braces) to make the string into
  429.  *    a valid Tcl list element.
  430.  *
  431.  * Results:
  432.  *    The return value is an overestimate of the number of characters
  433.  *    that will be needed by Tcl_ConvertElement to produce a valid
  434.  *    list element from string.  The word at *flagPtr is filled in
  435.  *    with a value needed by Tcl_ConvertElement when doing the actual
  436.  *    conversion.
  437.  *
  438.  * Side effects:
  439.  *    None.
  440.  *
  441.  *----------------------------------------------------------------------
  442.  */
  443.  
  444. int
  445. Tcl_ScanElement(string, flagPtr)
  446.     char *string;        /* String to convert to Tcl list element. */
  447.     int *flagPtr;        /* Where to store information to guide
  448.                  * Tcl_ConvertElement. */
  449. {
  450.     int flags, nestingLevel;
  451.     register char *p;
  452.  
  453.     /*
  454.      * This procedure and Tcl_ConvertElement together do two things:
  455.      *
  456.      * 1. They produce a proper list, one that will yield back the
  457.      * argument strings when evaluated or when disassembled with
  458.      * Tcl_SplitList.  This is the most important thing.
  459.      * 
  460.      * 2. They try to produce legible output, which means minimizing the
  461.      * use of backslashes (using braces instead).  However, there are
  462.      * some situations where backslashes must be used (e.g. an element
  463.      * like "{abc": the leading brace will have to be backslashed.  For
  464.      * each element, one of three things must be done:
  465.      *
  466.      * (a) Use the element as-is (it doesn't contain anything special
  467.      * characters).  This is the most desirable option.
  468.      *
  469.      * (b) Enclose the element in braces, but leave the contents alone.
  470.      * This happens if the element contains embedded space, or if it
  471.      * contains characters with special interpretation ($, [, ;, or \),
  472.      * or if it starts with a brace or double-quote, or if there are
  473.      * no characters in the element.
  474.      *
  475.      * (c) Don't enclose the element in braces, but add backslashes to
  476.      * prevent special interpretation of special characters.  This is a
  477.      * last resort used when the argument would normally fall under case
  478.      * (b) but contains unmatched braces.  It also occurs if the last
  479.      * character of the argument is a backslash.
  480.      *
  481.      * The procedure figures out how many bytes will be needed to store
  482.      * the result (actually, it overestimates).  It also collects information
  483.      * about the element in the form of a flags word.
  484.      */
  485.  
  486.     nestingLevel = 0;
  487.     flags = 0;
  488.     p = string;
  489.     if ((*p == '{') || (*p == '"') || (*p == 0)) {
  490.     flags |= USE_BRACES;
  491.     }
  492.     for ( ; *p != 0; p++) {
  493.     switch (*p) {
  494.         case '{':
  495.         nestingLevel++;
  496.         break;
  497.         case '}':
  498.         nestingLevel--;
  499.         if (nestingLevel < 0) {
  500.             flags |= TCL_DONT_USE_BRACES|BRACES_UNMATCHED;
  501.         }
  502.         break;
  503.         case '[':
  504.         case '$':
  505.         case ';':
  506.         case ' ':
  507.         case '\f':
  508.         case '\n':
  509.         case '\r':
  510.         case '\t':
  511.         case '\v':
  512.         flags |= USE_BRACES;
  513.         break;
  514.         case '\\':
  515.         if (p[1] == 0) {
  516.             flags = TCL_DONT_USE_BRACES;
  517.         } else {
  518.             int size;
  519.  
  520.             (void) Tcl_Backslash(p, &size);
  521.             p += size-1;
  522.             flags |= USE_BRACES;
  523.         }
  524.         break;
  525.     }
  526.     }
  527.     if (nestingLevel != 0) {
  528.     flags = TCL_DONT_USE_BRACES | BRACES_UNMATCHED;
  529.     }
  530.     *flagPtr = flags;
  531.  
  532.     /*
  533.      * Allow enough space to backslash every character plus leave
  534.      * two spaces for braces.
  535.      */
  536.  
  537.     return 2*(p-string) + 2;
  538. }
  539.  
  540. /*
  541.  *----------------------------------------------------------------------
  542.  *
  543.  * Tcl_ConvertElement --
  544.  *
  545.  *    This is a companion procedure to Tcl_ScanElement.  Given the
  546.  *    information produced by Tcl_ScanElement, this procedure converts
  547.  *    a string to a list element equal to that string.
  548.  *
  549.  * Results:
  550.  *    Information is copied to *dst in the form of a list element
  551.  *    identical to src (i.e. if Tcl_SplitList is applied to dst it
  552.  *    will produce a string identical to src).  The return value is
  553.  *    a count of the number of characters copied (not including the
  554.  *    terminating NULL character).
  555.  *
  556.  * Side effects:
  557.  *    None.
  558.  *
  559.  *----------------------------------------------------------------------
  560.  */
  561.  
  562. int
  563. Tcl_ConvertElement(src, dst, flags)
  564.     register char *src;        /* Source information for list element. */
  565.     char *dst;            /* Place to put list-ified element. */
  566.     int flags;            /* Flags produced by Tcl_ScanElement. */
  567. {
  568.     register char *p = dst;
  569.  
  570.     /*
  571.      * See the comment block at the beginning of the Tcl_ScanElement
  572.      * code for details of how this works.
  573.      */
  574.  
  575.     if ((flags & USE_BRACES) && !(flags & TCL_DONT_USE_BRACES)) {
  576.     *p = '{';
  577.     p++;
  578.     for ( ; *src != 0; src++, p++) {
  579.         *p = *src;
  580.     }
  581.     *p = '}';
  582.     p++;
  583.     } else if (*src == 0) {
  584.     /*
  585.      * If string is empty but can't use braces, then use special
  586.      * backslash sequence that maps to empty string.
  587.      */
  588.  
  589.     p[0] = '\\';
  590.     p[1] = '0';
  591.     p += 2;
  592.     } else {
  593.     for (; *src != 0 ; src++) {
  594.         switch (*src) {
  595.         case ']':
  596.         case '[':
  597.         case '$':
  598.         case ';':
  599.         case ' ':
  600.         case '\\':
  601.         case '"':
  602.             *p = '\\';
  603.             p++;
  604.             break;
  605.         case '{':
  606.         case '}':
  607.             if (flags & BRACES_UNMATCHED) {
  608.             *p = '\\';
  609.             p++;
  610.             }
  611.             break;
  612.         case '\f':
  613.             *p = '\\';
  614.             p++;
  615.             *p = 'f';
  616.             p++;
  617.             continue;
  618.         case '\n':
  619.             *p = '\\';
  620.             p++;
  621.             *p = 'n';
  622.             p++;
  623.             continue;
  624.         case '\r':
  625.             *p = '\\';
  626.             p++;
  627.             *p = 'r';
  628.             p++;
  629.             continue;
  630.         case '\t':
  631.             *p = '\\';
  632.             p++;
  633.             *p = 't';
  634.             p++;
  635.             continue;
  636.         case '\v':
  637.             *p = '\\';
  638.             p++;
  639.             *p = 'v';
  640.             p++;
  641.             continue;
  642.         }
  643.         *p = *src;
  644.         p++;
  645.     }
  646.     }
  647.     *p = '\0';
  648.     return p-dst;
  649. }
  650.  
  651. /*
  652.  *----------------------------------------------------------------------
  653.  *
  654.  * Tcl_Merge --
  655.  *
  656.  *    Given a collection of strings, merge them together into a
  657.  *    single string that has proper Tcl list structured (i.e.
  658.  *    Tcl_SplitList may be used to retrieve strings equal to the
  659.  *    original elements, and Tcl_Eval will parse the string back
  660.  *    into its original elements).
  661.  *
  662.  * Results:
  663.  *    The return value is the address of a dynamically-allocated
  664.  *    string containing the merged list.
  665.  *
  666.  * Side effects:
  667.  *    None.
  668.  *
  669.  *----------------------------------------------------------------------
  670.  */
  671.  
  672. char *
  673. Tcl_Merge(argc, argv)
  674.     int argc;            /* How many strings to merge. */
  675.     char **argv;        /* Array of string values. */
  676. {
  677. #   define LOCAL_SIZE 20
  678.     int localFlags[LOCAL_SIZE], *flagPtr;
  679.     int numChars;
  680.     char *result;
  681.     register char *dst;
  682.     int i;
  683.  
  684.     /*
  685.      * Pass 1: estimate space, gather flags.
  686.      */
  687.  
  688.     if (argc <= LOCAL_SIZE) {
  689.     flagPtr = localFlags;
  690.     } else {
  691.     flagPtr = (int *) ckalloc((unsigned) argc*sizeof(int));
  692.     }
  693.     numChars = 1;
  694.     for (i = 0; i < argc; i++) {
  695.     numChars += Tcl_ScanElement(argv[i], &flagPtr[i]) + 1;
  696.     }
  697.  
  698.     /*
  699.      * Pass two: copy into the result area.
  700.      */
  701.  
  702.     result = (char *) ckalloc((unsigned) numChars);
  703.     dst = result;
  704.     for (i = 0; i < argc; i++) {
  705.     numChars = Tcl_ConvertElement(argv[i], dst, flagPtr[i]);
  706.     dst += numChars;
  707.     *dst = ' ';
  708.     dst++;
  709.     }
  710.     if (dst == result) {
  711.     *dst = 0;
  712.     } else {
  713.     dst[-1] = 0;
  714.     }
  715.  
  716.     if (flagPtr != localFlags) {
  717.     ckfree((char *) flagPtr);
  718.     }
  719.     return result;
  720. }
  721.  
  722. /*
  723.  *----------------------------------------------------------------------
  724.  *
  725.  * Tcl_Concat --
  726.  *
  727.  *    Concatenate a set of strings into a single large string.
  728.  *
  729.  * Results:
  730.  *    The return value is dynamically-allocated string containing
  731.  *    a concatenation of all the strings in argv, with spaces between
  732.  *    the original argv elements.
  733.  *
  734.  * Side effects:
  735.  *    Memory is allocated for the result;  the caller is responsible
  736.  *    for freeing the memory.
  737.  *
  738.  *----------------------------------------------------------------------
  739.  */
  740.  
  741. char *
  742. Tcl_Concat(argc, argv)
  743.     int argc;            /* Number of strings to concatenate. */
  744.     char **argv;        /* Array of strings to concatenate. */
  745. {
  746.     int totalSize, i;
  747.     register char *p;
  748.     char *result;
  749.  
  750.     for (totalSize = 1, i = 0; i < argc; i++) {
  751.         totalSize += strlen(argv[i]) + 1;
  752.         }
  753.     result = (char *) ckalloc((unsigned) totalSize);
  754.     if (argc == 0) {
  755.         *result = '\0';
  756.         return result;
  757.         }
  758.     for (p = result, i = 0; i < argc; i++) {
  759.         char *element;
  760.         int length;
  761.     
  762.         /*
  763.          * Clip white space off the front and back of the string
  764.          * to generate a neater result, and ignore any empty
  765.          * elements.
  766.          */
  767.     
  768.         element = argv[i];
  769.         while (/*TGE*/((*element & 0x80) == 0) && /*TGE*/isspace(*element)) {
  770.             element++;
  771.             }
  772.         for (length = strlen(element);
  773.                 (length > 0) &&
  774.                 (/*TGE*/((element[length-1] & 0x80) == 0) && /*TGE*/isspace(element[length-1]));
  775.                 length--)
  776.             {
  777.             /* Null loop body. */
  778.             }
  779.         if (length == 0) {
  780.             continue;
  781.             }
  782.         (void) strncpy(p, element, length);
  783.         p += length;
  784.         *p = ' ';
  785.         p++;
  786.         }
  787.     if (p != result) {
  788.         p[-1] = 0;
  789.         }
  790.     else {
  791.         *p = 0;
  792.         }
  793.     return result;
  794.     }
  795.  
  796. /*
  797.  *----------------------------------------------------------------------
  798.  *
  799.  * Tcl_StringMatch --
  800.  *
  801.  *    See if a particular string matches a particular pattern.
  802.  *
  803.  * Results:
  804.  *    The return value is 1 if string matches pattern, and
  805.  *    0 otherwise.  The matching operation permits the following
  806.  *    special characters in the pattern: *?\[] (see the manual
  807.  *    entry for details on what these mean).
  808.  *
  809.  * Side effects:
  810.  *    None.
  811.  *
  812.  *----------------------------------------------------------------------
  813.  */
  814.  
  815. int
  816. Tcl_StringMatch(string, pattern)
  817.     register char *string;    /* String. */
  818.     register char *pattern;    /* Pattern, which may contain
  819.                  * special characters. */
  820. {
  821.     char c2;
  822.  
  823.     while (1) {
  824.     /* See if we're at the end of both the pattern and the string.
  825.      * If so, we succeeded.  If we're at the end of the pattern
  826.      * but not at the end of the string, we failed.
  827.      */
  828.     
  829.     if (*pattern == 0) {
  830.         if (*string == 0) {
  831.         return 1;
  832.         } else {
  833.         return 0;
  834.         }
  835.     }
  836.     if ((*string == 0) && (*pattern != '*')) {
  837.         return 0;
  838.     }
  839.  
  840.     /* Check for a "*" as the next pattern character.  It matches
  841.      * any substring.  We handle this by calling ourselves
  842.      * recursively for each postfix of string, until either we
  843.      * match or we reach the end of the string.
  844.      */
  845.     
  846.     if (*pattern == '*') {
  847.         pattern += 1;
  848.         if (*pattern == 0) {
  849.         return 1;
  850.         }
  851.         while (*string != 0) {
  852.         if (Tcl_StringMatch(string, pattern)) {
  853.             return 1;
  854.         }
  855.         string += 1;
  856.         }
  857.         return 0;
  858.     }
  859.     
  860.     /* Check for a "?" as the next pattern character.  It matches
  861.      * any single character.
  862.      */
  863.  
  864.     if (*pattern == '?') {
  865.         goto thisCharOK;
  866.     }
  867.  
  868.     /* Check for a "[" as the next pattern character.  It is followed
  869.      * by a list of characters that are acceptable, or by a range
  870.      * (two characters separated by "-").
  871.      */
  872.     
  873.     if (*pattern == '[') {
  874.         pattern += 1;
  875.         while (1) {
  876.         if ((*pattern == ']') || (*pattern == 0)) {
  877.             return 0;
  878.         }
  879.         if (*pattern == *string) {
  880.             break;
  881.         }
  882.         if (pattern[1] == '-') {
  883.             c2 = pattern[2];
  884.             if (c2 == 0) {
  885.             return 0;
  886.             }
  887.             if ((*pattern <= *string) && (c2 >= *string)) {
  888.             break;
  889.             }
  890.             if ((*pattern >= *string) && (c2 <= *string)) {
  891.             break;
  892.             }
  893.             pattern += 2;
  894.         }
  895.         pattern += 1;
  896.         }
  897.         while ((*pattern != ']') && (*pattern != 0)) {
  898.         pattern += 1;
  899.         }
  900.         goto thisCharOK;
  901.     }
  902.     
  903.     /* If the next pattern character is '/', just strip off the '/'
  904.      * so we do exact matching on the character that follows.
  905.      */
  906.     
  907.     if (*pattern == '\\') {
  908.         pattern += 1;
  909.         if (*pattern == 0) {
  910.         return 0;
  911.         }
  912.     }
  913.  
  914.     /* There's no special character.  Just make sure that the next
  915.      * characters of each string match.
  916.      */
  917.     
  918.     if (*pattern != *string) {
  919.         return 0;
  920.     }
  921.  
  922.     thisCharOK: pattern += 1;
  923.     string += 1;
  924.     }
  925. }
  926.  
  927. /*
  928.  *----------------------------------------------------------------------
  929.  *
  930.  * Tcl_SetResult --
  931.  *
  932.  *    Arrange for "string" to be the Tcl return value.
  933.  *
  934.  * Results:
  935.  *    None.
  936.  *
  937.  * Side effects:
  938.  *    interp->result is left pointing either to "string" (if "copy" is 0)
  939.  *    or to a copy of string.
  940.  *
  941.  *----------------------------------------------------------------------
  942.  */
  943.  
  944. void
  945. Tcl_SetResult(interp, string, freeProc)
  946.     Tcl_Interp *interp;        /* Interpreter with which to associate the
  947.                  * return value. */
  948.     char *string;        /* Value to be returned.  If NULL,
  949.                  * the result is set to an empty string. */
  950.     Tcl_FreeProc *freeProc;    /* Gives information about the string:
  951.                  * TCL_STATIC, TCL_VOLATILE, or the address
  952.                  * of a Tcl_FreeProc such as free. */
  953. {
  954.     register Interp *iPtr = (Interp *) interp;
  955.     int length;
  956.     Tcl_FreeProc *oldFreeProc = iPtr->freeProc;
  957.     char *oldResult = iPtr->result;
  958.  
  959.     iPtr->freeProc = freeProc;
  960.     if (string == NULL) {
  961.     iPtr->resultSpace[0] = 0;
  962.     iPtr->result = iPtr->resultSpace;
  963.     iPtr->freeProc = 0;
  964.     } else if (freeProc == TCL_VOLATILE) {
  965.     length = strlen(string);
  966.     if (length > TCL_RESULT_SIZE) {
  967.         iPtr->result = (char *) ckalloc((unsigned) length+1);
  968.         iPtr->freeProc = (Tcl_FreeProc *) free;
  969.     } else {
  970.         iPtr->result = iPtr->resultSpace;
  971.         iPtr->freeProc = 0;
  972.     }
  973.     strcpy(iPtr->result, string);
  974.     } else {
  975.     iPtr->result = string;
  976.     }
  977.  
  978.     /*
  979.      * If the old result was dynamically-allocated, free it up.  Do it
  980.      * here, rather than at the beginning, in case the _new result value
  981.      * was part of the old result value.
  982.      */
  983.  
  984.     if (oldFreeProc != 0) {
  985.     (*oldFreeProc)(oldResult);
  986.     }
  987. }
  988.  
  989. /*
  990.  *----------------------------------------------------------------------
  991.  *
  992.  * Tcl_AppendResult --
  993.  *
  994.  *    Append a variable number of strings onto the result already
  995.  *    present for an interpreter.
  996.  *
  997.  * Results:
  998.  *    None.
  999.  *
  1000.  * Side effects:
  1001.  *    The result in the interpreter given by the first argument
  1002.  *    is extended by the strings given by the second and following
  1003.  *    arguments (up to a terminating NULL argument).
  1004.  *
  1005.  *----------------------------------------------------------------------
  1006.  */
  1007.  
  1008.     /* VARARGS2 */
  1009.  
  1010. #ifdef macintosh
  1011.  
  1012. void
  1013. Tcl_AppendResult(Tcl_Interp *interp, ...)
  1014. {
  1015.  
  1016. #else
  1017.  
  1018. #ifndef lint
  1019. void
  1020. Tcl_AppendResult(va_alist)
  1021. #else
  1022. void
  1023.     /* VARARGS2 */ /* ARGSUSED */
  1024. Tcl_AppendResult(interp, p, va_alist)
  1025.     Tcl_Interp *interp;        /* Interpreter whose result is to be
  1026.                  * extended. */
  1027.     char *p;            /* One or more strings to add to the
  1028.                  * result, terminated with NULL. */
  1029. #endif
  1030.     va_dcl
  1031. {
  1032.  
  1033. #endif
  1034.  
  1035.     va_list argList;
  1036.     Interp *iPtr;
  1037.     char *string;
  1038.     int newSpace;
  1039.  
  1040.     /*
  1041.      * First, scan through all the arguments to see how much space is
  1042.      * needed.
  1043.      */
  1044.  
  1045. #ifdef macintosh
  1046.     va_start(argList, interp);
  1047. #else
  1048.     va_start(argList);
  1049. #endif
  1050.  
  1051. #ifdef macintosh
  1052.     iPtr = (Interp *) interp;
  1053. #else
  1054.     iPtr = va_arg(argList, Interp *);
  1055. #endif
  1056.  
  1057.     newSpace = 0;
  1058.     while (1) {
  1059.         string = va_arg(argList, char *);
  1060.         if (string == NULL) {
  1061.             break;
  1062.             }
  1063.         newSpace += strlen(string);
  1064.         }
  1065.     
  1066.     va_end(argList);
  1067.  
  1068.     /*
  1069.      * If the append buffer isn't already setup and large enough
  1070.      * to hold the _new data, set it up.
  1071.      */
  1072.  
  1073.     if ((iPtr->result != iPtr->appendResult)
  1074.        || ((newSpace + iPtr->appendUsed) >= iPtr->appendAvl)) {
  1075.        SetupAppendBuffer(iPtr, newSpace);
  1076.     }
  1077.  
  1078.     /*
  1079.      * Final step:  go through all the argument strings again, copying
  1080.      * them into the buffer.
  1081.      */
  1082.  
  1083. #ifdef macintosh
  1084.     va_start(argList, interp);
  1085. #else
  1086.     va_start(argList);
  1087.     (void) va_arg(argList, Tcl_Interp *);
  1088. #endif
  1089.  
  1090.     while (1) {
  1091.         string = va_arg(argList, char *);
  1092.         if (string == NULL) {
  1093.             break;
  1094.             }
  1095.         strcpy(iPtr->appendResult + iPtr->appendUsed, string);
  1096.         iPtr->appendUsed += strlen(string);
  1097.         }
  1098.     
  1099.     va_end(argList);
  1100.     }
  1101.  
  1102. /*
  1103.  *----------------------------------------------------------------------
  1104.  *
  1105.  * Tcl_AppendElement --
  1106.  *
  1107.  *    Convert a string to a valid Tcl list element and append it
  1108.  *    to the current result (which is ostensibly a list).
  1109.  *
  1110.  * Results:
  1111.  *    None.
  1112.  *
  1113.  * Side effects:
  1114.  *    The result in the interpreter given by the first argument
  1115.  *    is extended with a list element converted from string.  If
  1116.  *    the original result wasn't empty, then a blank is added before
  1117.  *    the converted list element.
  1118.  *
  1119.  *----------------------------------------------------------------------
  1120.  */
  1121.  
  1122. void
  1123. Tcl_AppendElement(interp, string, noSep)
  1124.     Tcl_Interp *interp;        /* Interpreter whose result is to be
  1125.                  * extended. */
  1126.     char *string;        /* String to convert to list element and
  1127.                  * add to result. */
  1128.     int noSep;            /* If non-zero, then don't output a
  1129.                  * space character before this element,
  1130.                  * even if the element isn't the first
  1131.                  * thing in the output buffer. */
  1132. {
  1133.     register Interp *iPtr = (Interp *) interp;
  1134.     int size, flags;
  1135.     char *dst;
  1136.  
  1137.     /*
  1138.      * See how much space is needed, and grow the append buffer if
  1139.      * needed to accommodate the list element.
  1140.      */
  1141.  
  1142.     size = Tcl_ScanElement(string, &flags) + 1;
  1143.     if ((iPtr->result != iPtr->appendResult)
  1144.        || ((size + iPtr->appendUsed) >= iPtr->appendAvl)) {
  1145.        SetupAppendBuffer(iPtr, size+iPtr->appendUsed);
  1146.     }
  1147.  
  1148.     /*
  1149.      * Convert the string into a list element and copy it to the
  1150.      * buffer that's forming.
  1151.      */
  1152.  
  1153.     dst = iPtr->appendResult + iPtr->appendUsed;
  1154.     if (!noSep && (iPtr->appendUsed != 0)) {
  1155.     iPtr->appendUsed++;
  1156.     *dst = ' ';
  1157.     dst++;
  1158.     }
  1159.     iPtr->appendUsed += Tcl_ConvertElement(string, dst, flags);
  1160. }
  1161.  
  1162. /*
  1163.  *----------------------------------------------------------------------
  1164.  *
  1165.  * SetupAppendBuffer --
  1166.  *
  1167.  *    This procedure makes sure that there is an append buffer
  1168.  *    properly initialized for interp, and that it has at least
  1169.  *    enough room to accommodate newSpace _new bytes of information.
  1170.  *
  1171.  * Results:
  1172.  *    None.
  1173.  *
  1174.  * Side effects:
  1175.  *    None.
  1176.  *
  1177.  *----------------------------------------------------------------------
  1178.  */
  1179.  
  1180. static void
  1181. SetupAppendBuffer(iPtr, newSpace)
  1182.     register Interp *iPtr;    /* Interpreter whose result is being set up. */
  1183.     int newSpace;        /* Make sure that at least this many bytes
  1184.                  * of _new information may be added. */
  1185. {
  1186.     int totalSpace;
  1187.  
  1188.     /*
  1189.      * Make the append buffer larger, if that's necessary, then
  1190.      * copy the current result into the append buffer and make the
  1191.      * append buffer the official Tcl result.
  1192.      */
  1193.  
  1194.     if (iPtr->result != iPtr->appendResult) {
  1195.     /*
  1196.      * If an oversized buffer was used recently, then free it up
  1197.      * so we go back to a smaller buffer.  This avoids tying up
  1198.      * memory forever after a large operation.
  1199.      */
  1200.  
  1201.     if (iPtr->appendAvl > 500) {
  1202.         ckfree(iPtr->appendResult);
  1203.         iPtr->appendResult = NULL;
  1204.         iPtr->appendAvl = 0;
  1205.     }
  1206.     iPtr->appendUsed = strlen(iPtr->result);
  1207.     }
  1208.     totalSpace = newSpace + iPtr->appendUsed;
  1209.     if (totalSpace >= iPtr->appendAvl) {
  1210.     char *_new;
  1211.  
  1212.     if (totalSpace < 100) {
  1213.         totalSpace = 200;
  1214.     } else {
  1215.         totalSpace *= 2;
  1216.     }
  1217.     _new = (char *) ckalloc((unsigned) totalSpace);
  1218.     strcpy(_new, iPtr->result);
  1219.     if (iPtr->appendResult != NULL) {
  1220.         ckfree(iPtr->appendResult);
  1221.     }
  1222.     iPtr->appendResult = _new;
  1223.     iPtr->appendAvl = totalSpace;
  1224.     } else if (iPtr->result != iPtr->appendResult) {
  1225.     strcpy(iPtr->appendResult, iPtr->result);
  1226.     }
  1227.     Tcl_FreeResult(iPtr);
  1228.     iPtr->result = iPtr->appendResult;
  1229. }
  1230.  
  1231. /*
  1232.  *----------------------------------------------------------------------
  1233.  *
  1234.  * Tcl_ResetResult --
  1235.  *
  1236.  *    This procedure restores the result area for an interpreter
  1237.  *    to its default initialized state, freeing up any memory that
  1238.  *    may have been allocated for the result and clearing any
  1239.  *    error information for the interpreter.
  1240.  *
  1241.  * Results:
  1242.  *    None.
  1243.  *
  1244.  * Side effects:
  1245.  *    None.
  1246.  *
  1247.  *----------------------------------------------------------------------
  1248.  */
  1249.  
  1250. void
  1251. Tcl_ResetResult(interp)
  1252.     Tcl_Interp *interp;        /* Interpreter for which to clear result. */
  1253. {
  1254.     register Interp *iPtr = (Interp *) interp;
  1255.  
  1256.     Tcl_FreeResult(iPtr);
  1257.     iPtr->result = iPtr->resultSpace;
  1258.     iPtr->resultSpace[0] = 0;
  1259.     iPtr->flags &=
  1260.         ~(ERR_ALREADY_LOGGED | ERR_IN_PROGRESS | ERROR_CODE_SET);
  1261. }
  1262.  
  1263. /*
  1264.  *----------------------------------------------------------------------
  1265.  *
  1266.  * Tcl_SetErrorCode --
  1267.  *
  1268.  *    This procedure is called to record machine-readable information
  1269.  *    about an error that is about to be returned.
  1270.  *
  1271.  * Results:
  1272.  *    None.
  1273.  *
  1274.  * Side effects:
  1275.  *    The errorCode global variable is modified to hold all of the
  1276.  *    arguments to this procedure, in a list form with each argument
  1277.  *    becoming one element of the list.  A flag is set internally
  1278.  *    to remember that errorCode has been set, so the variable doesn't
  1279.  *    get set automatically when the error is returned.
  1280.  *
  1281.  *----------------------------------------------------------------------
  1282.  */
  1283.     /* VARARGS2 */
  1284.  
  1285. #ifdef macintosh
  1286.  
  1287. void
  1288. Tcl_SetErrorCode(Tcl_Interp *interp, ...)
  1289.  
  1290. #else
  1291.  
  1292. #ifndef lint
  1293. void
  1294. Tcl_SetErrorCode(va_alist)
  1295. #else
  1296. void
  1297.     /* VARARGS2 */ /* ARGSUSED */
  1298. Tcl_SetErrorCode(interp, p, va_alist)
  1299.     Tcl_Interp *interp;        /* Interpreter whose errorCode variable is
  1300.                  * to be set. */
  1301.     char *p;            /* One or more elements to add to errorCode,
  1302.                  * terminated with NULL. */
  1303. #endif
  1304.     va_dcl
  1305.  
  1306. #endif
  1307.  
  1308. {
  1309.     va_list argList;
  1310.     char *string;
  1311.     int flags;
  1312.     Interp *iPtr;
  1313.  
  1314.     /*
  1315.      * Scan through the arguments one at a time, appending them to
  1316.      * $errorCode as list elements.
  1317.      */
  1318.  
  1319. #ifdef macintosh
  1320.     va_start(argList, interp);
  1321. #else
  1322.     va_start(argList);
  1323. #endif
  1324.  
  1325. #ifdef macintosh
  1326.     iPtr = (Interp *) interp;
  1327. #else
  1328.     iPtr = va_arg(argList, Interp *);
  1329. #endif
  1330.  
  1331.     flags = TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT;
  1332.     while (1) {
  1333.         string = va_arg(argList, char *);
  1334.         if (string == NULL) {
  1335.             break;
  1336.             }
  1337.         (void) Tcl_SetVar2((Tcl_Interp *) iPtr, "errorCode",
  1338.             (char *) NULL, string, flags);
  1339.         flags |= TCL_APPEND_VALUE;
  1340.         }
  1341.         
  1342.     va_end(argList);
  1343.     iPtr->flags |= ERROR_CODE_SET;
  1344.     }
  1345.  
  1346. /*
  1347.  *----------------------------------------------------------------------
  1348.  *
  1349.  * TclGetListIndex --
  1350.  *
  1351.  *    Parse a list index, which may be either an integer or the
  1352.  *    value "end".
  1353.  *
  1354.  * Results:
  1355.  *    The return value is either TCL_OK or TCL_ERROR.  If it is
  1356.  *    TCL_OK, then the index corresponding to string is left in
  1357.  *    *indexPtr.  If the return value is TCL_ERROR, then string
  1358.  *    was bogus;  an error message is returned in interp->result.
  1359.  *    If a negative index is specified, it is rounded up to 0.
  1360.  *    The index value may be larger than the size of the list
  1361.  *    (this happens when "end" is specified).
  1362.  *
  1363.  * Side effects:
  1364.  *    None.
  1365.  *
  1366.  *----------------------------------------------------------------------
  1367.  */
  1368.  
  1369. int
  1370. TclGetListIndex(interp, string, indexPtr)
  1371.     Tcl_Interp *interp;            /* Interpreter for error reporting. */
  1372.     char *string;            /* String containing list index. */
  1373.     int *indexPtr;            /* Where to store index. */
  1374. {
  1375.     if (isdigit(*string) || (*string == '-')) {
  1376.     if (Tcl_GetInt(interp, string, indexPtr) != TCL_OK) {
  1377.         return TCL_ERROR;
  1378.     }
  1379.     if (*indexPtr < 0) {
  1380.         *indexPtr = 0;
  1381.     }
  1382.     } else if (strncmp(string, "end", strlen(string)) == 0) {
  1383.     *indexPtr = 1<<30;
  1384.     } else {
  1385.     Tcl_AppendResult(interp, "bad index \"", string,
  1386.         "\": must be integer or \"end\"", (char *) NULL);
  1387.     return TCL_ERROR;
  1388.     }
  1389.     return TCL_OK;
  1390. }
  1391.  
  1392. /*
  1393.  *----------------------------------------------------------------------
  1394.  *
  1395.  * TclCompileRegexp --
  1396.  *
  1397.  *    Compile a regular expression into a form suitable for fast
  1398.  *    matching.  This procedure retains a small cache of pre-compiled
  1399.  *    regular expressions in the interpreter, in order to avoid
  1400.  *    compilation costs as much as possible.
  1401.  *
  1402.  * Results:
  1403.  *    The return value is a pointer to the compiled form of string,
  1404.  *    suitable for passing to regexec.  If an error occurred while
  1405.  *    compiling the pattern, then NULL is returned and an error
  1406.  *    message is left in interp->result.
  1407.  *
  1408.  * Side effects:
  1409.  *    The cache of compiled regexp's in interp will be modified to
  1410.  *    hold information for string, if such information isn't already
  1411.  *    present in the cache.
  1412.  *
  1413.  *----------------------------------------------------------------------
  1414.  */
  1415.  
  1416. regexp *
  1417. TclCompileRegexp(interp, string)
  1418.     Tcl_Interp *interp;            /* For use in error reporting. */
  1419.     char *string;            /* String for which to produce
  1420.                      * compiled regular expression. */
  1421. {
  1422.     register Interp *iPtr = (Interp *) interp;
  1423.     int i, length;
  1424.     regexp *result;
  1425.  
  1426.     length = strlen(string);
  1427.     for (i = 0; i < NUM_REGEXPS; i++) {
  1428.     if ((length == iPtr->patLengths[i])
  1429.         && (strcmp(string, iPtr->patterns[i]) == 0)) {
  1430.         /*
  1431.          * Move the matched pattern to the first slot in the
  1432.          * cache and shift the other patterns down one position.
  1433.          */
  1434.  
  1435.         if (i != 0) {
  1436.         int j;
  1437.         char *cachedString;
  1438.  
  1439.         cachedString = iPtr->patterns[i];
  1440.         result = iPtr->regexps[i];
  1441.         for (j = i-1; j >= 0; j--) {
  1442.             iPtr->patterns[j+1] = iPtr->patterns[j];
  1443.             iPtr->patLengths[j+1] = iPtr->patLengths[j];
  1444.             iPtr->regexps[j+1] = iPtr->regexps[j];
  1445.         }
  1446.         iPtr->patterns[0] = cachedString;
  1447.         iPtr->patLengths[0] = length;
  1448.         iPtr->regexps[0] = result;
  1449.         }
  1450.         return iPtr->regexps[0];
  1451.     }
  1452.     }
  1453.  
  1454.     /*
  1455.      * No match in the cache.  Compile the string and add it to the
  1456.      * cache.
  1457.      */
  1458.  
  1459.     tclRegexpError = NULL;
  1460.     result = regcomp(string);
  1461.     if (tclRegexpError != NULL) {
  1462.     Tcl_AppendResult(interp,
  1463.         "couldn't compile regular expression pattern: ",
  1464.         tclRegexpError, (char *) NULL);
  1465.     return NULL;
  1466.     }
  1467.     if (iPtr->patterns[NUM_REGEXPS-1] != NULL) {
  1468.     ckfree(iPtr->patterns[NUM_REGEXPS-1]);
  1469.     ckfree((char *) iPtr->regexps[NUM_REGEXPS-1]);
  1470.     }
  1471.     for (i = NUM_REGEXPS - 2; i >= 0; i--) {
  1472.     iPtr->patterns[i+1] = iPtr->patterns[i];
  1473.     iPtr->patLengths[i+1] = iPtr->patLengths[i];
  1474.     iPtr->regexps[i+1] = iPtr->regexps[i];
  1475.     }
  1476.     iPtr->patterns[0] = (char *) ckalloc((unsigned) (length+1));
  1477.     strcpy(iPtr->patterns[0], string);
  1478.     iPtr->patLengths[0] = length;
  1479.     iPtr->regexps[0] = result;
  1480.     return result;
  1481. }
  1482.  
  1483. /*
  1484.  *----------------------------------------------------------------------
  1485.  *
  1486.  * regerror --
  1487.  *
  1488.  *    This procedure is invoked by the Henry Spencer's regexp code
  1489.  *    when an error occurs.  It saves the error message so it can
  1490.  *    be seen by the code that called Spencer's code.
  1491.  *
  1492.  * Results:
  1493.  *    None.
  1494.  *
  1495.  * Side effects:
  1496.  *    The value of "string" is saved in "tclRegexpError".
  1497.  *
  1498.  *----------------------------------------------------------------------
  1499.  */
  1500.  
  1501. void
  1502. regerror(string)
  1503.     char *string;            /* Error message. */
  1504. {
  1505.     tclRegexpError = string;
  1506. }
  1507.